package com.xyht.sca_s.student_manage_system.modules.goods.service.impl;

import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.xyht.sca_s.student_manage_system.common.commonReturn.CommonCodeEnum;
import com.xyht.sca_s.student_manage_system.common.commonReturn.CommonResult;
import com.xyht.sca_s.student_manage_system.common.commonReturn.ResponseResult;
import com.xyht.sca_s.student_manage_system.modules.goods.entity.SmsGoods;
import com.xyht.sca_s.student_manage_system.modules.goods.entity.SmsGoodsClassification;
import com.xyht.sca_s.student_manage_system.modules.goods.entity.SmsGoodsStock;
import com.xyht.sca_s.student_manage_system.modules.goods.entity.SmsGoodsStockLog;
import com.xyht.sca_s.student_manage_system.modules.goods.entity.req.SmsGoodsStockAddReq;
import com.xyht.sca_s.student_manage_system.modules.goods.entity.resp.SmsGoodsResp;
import com.xyht.sca_s.student_manage_system.modules.goods.entity.resp.SmsGoodsStockLogResp;
import com.xyht.sca_s.student_manage_system.modules.goods.mapper.SmsGoodsClassificationMapper;
import com.xyht.sca_s.student_manage_system.modules.goods.mapper.SmsGoodsMapper;
import com.xyht.sca_s.student_manage_system.modules.goods.mapper.SmsGoodsStockLogMapper;
import com.xyht.sca_s.student_manage_system.modules.goods.mapper.SmsGoodsStockMapper;
import com.xyht.sca_s.student_manage_system.modules.goods.service.SmsGoodsStockService;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.util.List;
import java.util.stream.Collectors;

import static com.xyht.sca_s.student_manage_system.common.util.ParamCheckUtil.isNullOrEmpty;
import static com.xyht.sca_s.student_manage_system.modules.goods.constant.IsOnConstant.IN_STOCK;
import static com.xyht.sca_s.student_manage_system.modules.goods.constant.IsOnConstant.OUT_STOCK;

/**
 * <p>
 * 物品库存表(--迎新) 服务实现类
 * </p>
 *
 * @author XYHT
 * @since 2024-01-17
 */
@Service
public class SmsGoodsStockServiceImpl extends ServiceImpl<SmsGoodsStockMapper, SmsGoodsStock> implements SmsGoodsStockService {


    @Resource
    private SmsGoodsStockMapper goodsStockMapper;
    @Resource
    private SmsGoodsStockLogMapper goodsStockLogMapper;
    @Resource
    private SmsGoodsClassificationMapper goodsClassificationMapper;
    @Resource
    private SmsGoodsMapper goodsMapper;


    @Override
    @Transactional
    public ResponseResult addGoodsStock(String userId, SmsGoodsStockAddReq addReq) {
        if (isNullOrEmpty(addReq.getGoodsId(),addReq.getClassificationId(),addReq.getStockQuantity())) {
            return CommonResult.failed(CommonCodeEnum.INVALID_PARAM);
        }

        //校验物品分类是否存在
        SmsGoodsClassification smsGoodsClassification = goodsClassificationMapper.selectById(addReq.getClassificationId());
        if (isNullOrEmpty(smsGoodsClassification)) {
            return CommonResult.failed(CommonCodeEnum.GOODS_CLASSIFICATION_NOT_EXIST);
        }

        //校验物品是否存在
        SmsGoods smsGoods = goodsMapper.selectById(addReq.getGoodsId());
        if (isNullOrEmpty(smsGoods)) {
            return CommonResult.failed(CommonCodeEnum.GOODS_NOT_EXIST);
        }
        //校验物品分类库存
        SmsGoodsStock smsGoodsStock = goodsStockMapper.selectById(addReq.getId());
        if (isNullOrEmpty(smsGoodsStock)) {
            return CommonResult.failed(CommonCodeEnum.GOODS_STOCK_NOT_EXIST);
        }
        //增加的库存数
        Integer stockQuantity = addReq.getStockQuantity();
        if (stockQuantity < 0) {
            return CommonResult.failed(CommonCodeEnum.INVALID_PARAM);
        }
        Integer oldStockQuantity = smsGoodsStock.getStockQuantity();
        int sum = oldStockQuantity + stockQuantity;
        smsGoodsStock.setStockQuantity(sum);
        smsGoodsStock.setUserId(userId);
        int updNum = goodsStockMapper.updateById(smsGoodsStock);
        if (updNum != 1) {
            return CommonResult.failed(CommonCodeEnum.FAIL);
        }
        //库存日志
        SmsGoodsStockLog smsGoodsStockLog = new SmsGoodsStockLog();
        smsGoodsStockLog.setGoodsId(addReq.getGoodsId());
        smsGoodsStockLog.setClassificationId(addReq.getClassificationId());
        String goodsInfo = JSONObject.toJSONString(smsGoods);
        smsGoodsStockLog.setGoodsInfo(goodsInfo);
        smsGoodsStockLog.setStockType(IN_STOCK);
        smsGoodsStockLog.setUserId(userId);
        smsGoodsStockLog.setInQuantity(addReq.getStockQuantity());
        int insertNum = goodsStockLogMapper.insert(smsGoodsStockLog);
        if (insertNum != 1) {
            return CommonResult.failed(CommonCodeEnum.FAIL);
        }
        return CommonResult.success();
    }

    @Override
    @Transactional
    public ResponseResult reduceGoodsStock(SmsGoodsStockAddReq reduceReq, String userId) {
        if (isNullOrEmpty(reduceReq.getId(),reduceReq.getGoodsId(),reduceReq.getClassificationId(),reduceReq.getStockQuantity())) {
            return CommonResult.failed(CommonCodeEnum.INVALID_PARAM);
        }
        //校验物品分类是否存在
        SmsGoodsClassification smsGoodsClassification = goodsClassificationMapper.selectById(reduceReq.getClassificationId());
        if (isNullOrEmpty(smsGoodsClassification)) {
            return CommonResult.failed(CommonCodeEnum.GOODS_CLASSIFICATION_NOT_EXIST);
        }

        //校验物品是否存在
        SmsGoods smsGoods = goodsMapper.selectById(reduceReq.getGoodsId());
        if (isNullOrEmpty(smsGoods)) {
            return CommonResult.failed(CommonCodeEnum.GOODS_NOT_EXIST);
        }
        //校验物品分类库存
        SmsGoodsStock smsGoodsStock = goodsStockMapper.selectById(reduceReq.getId());
        if (isNullOrEmpty(smsGoodsStock)) {
            return CommonResult.failed(CommonCodeEnum.GOODS_STOCK_NOT_EXIST);
        }
        //较少库存数
        Integer reduceStockQuantity = reduceReq.getStockQuantity();
        //库存数
        Integer oldStockQuantity = smsGoodsStock.getStockQuantity();
        if (reduceStockQuantity < 0) {
            return CommonResult.failed(CommonCodeEnum.INVALID_PARAM);
        }
        if (reduceStockQuantity > oldStockQuantity) {
            return CommonResult.failed(CommonCodeEnum.GOODS_STOCK_REDUCE_OVER);
        }
        int stockQuantity = oldStockQuantity - reduceStockQuantity;
        smsGoodsStock.setStockQuantity(stockQuantity);
        int updNum = goodsStockMapper.updateById(smsGoodsStock);
        if (updNum != 1) {
            return CommonResult.failed(CommonCodeEnum.FAIL);
        }
        //库存日志
        SmsGoodsStockLog smsGoodsStockLog = new SmsGoodsStockLog();
        smsGoodsStockLog.setGoodsId(reduceReq.getGoodsId());
        smsGoodsStockLog.setClassificationId(reduceReq.getClassificationId());
        String goodsInfo = JSONObject.toJSONString(smsGoods);
        smsGoodsStockLog.setGoodsInfo(goodsInfo);
        smsGoodsStockLog.setStockType(OUT_STOCK);
        smsGoodsStockLog.setUserId(userId);
        smsGoodsStockLog.setInQuantity(reduceReq.getStockQuantity());
        int insertNum = goodsStockLogMapper.insert(smsGoodsStockLog);
        if (insertNum != 1) {
            return CommonResult.failed(CommonCodeEnum.FAIL);
        }
        return CommonResult.success();
    }

    @Override
    public ResponseResult getGoodsStockHistoryList(Integer pageNum, Integer pageSize, String searchStr, Integer stockType, String classificationId) {
        Page<SmsGoodsStockLog> page = new Page<>(pageNum,pageSize);
        LambdaQueryWrapper<SmsGoodsStockLog> goodsStockLogLambdaQueryWrapper = new LambdaQueryWrapper<SmsGoodsStockLog>()
                .orderByDesc(SmsGoodsStockLog::getCreateTime);
        if (!isNullOrEmpty(searchStr)) {
            List<SmsGoods> goodsList = goodsMapper.selectList(new LambdaQueryWrapper<SmsGoods>().like(SmsGoods::getGoodsName, searchStr));
            List<String> goodsIdList = goodsList.stream().map(SmsGoods::getId).collect(Collectors.toList());
            if (!goodsList.isEmpty()) {
                goodsStockLogLambdaQueryWrapper.in(SmsGoodsStockLog::getGoodsId,goodsIdList);
            }else {
                goodsStockLogLambdaQueryWrapper.in(SmsGoodsStockLog::getGoodsId,"");
            }

        }
        if (!isNullOrEmpty(stockType)) {
            goodsStockLogLambdaQueryWrapper.eq(SmsGoodsStockLog::getStockType,stockType);
        }
        if (!isNullOrEmpty(classificationId)) {
            goodsStockLogLambdaQueryWrapper.in(SmsGoodsStockLog::getClassificationId,classificationId);
        }

        goodsStockLogMapper.selectPage(page,goodsStockLogLambdaQueryWrapper);
        List<SmsGoodsStockLogResp> goodsStockLogList = page.getRecords()
                .stream().map(smsGoodsStockLog -> {
                    SmsGoodsStockLogResp smsGoodsStockLogResp = new SmsGoodsStockLogResp();
                    SmsGoodsResp smsGoodsResp = new SmsGoodsResp();

                    //物品信息
                    SmsGoods smsGoods = JSONObject.parseObject(smsGoodsStockLog.getGoodsInfo(), SmsGoods.class);
                    if (!isNullOrEmpty(smsGoods)) {
                        BeanUtils.copyProperties(smsGoods,smsGoodsResp);
                    }
                    SmsGoodsClassification smsGoodsClassification = goodsClassificationMapper.selectById(smsGoodsStockLog.getClassificationId());
                    if (!isNullOrEmpty(smsGoodsClassification)) {
                        smsGoodsStockLogResp.setClassificationId(smsGoodsClassification.getId());
                        smsGoodsStockLogResp.setClassificationName(smsGoodsClassification.getClassificationName());
                    }
                    smsGoodsStockLogResp.setId(smsGoodsStockLog.getId());
                    smsGoodsStockLogResp.setGoodsInfo(smsGoodsResp);
                    Integer type = smsGoodsStockLog.getStockType();
                    if (type == IN_STOCK) {
                        smsGoodsStockLogResp.setStockType(IN_STOCK);
                        smsGoodsStockLogResp.setInQuantity(smsGoodsStockLog.getInQuantity());
                    }else {
                        smsGoodsStockLogResp.setStockType(OUT_STOCK);
                        smsGoodsStockLogResp.setInQuantity(smsGoodsStockLog.getOutQuantity());
                    }
                    return smsGoodsStockLogResp;
                })
                .collect(Collectors.toList());
        int total = (int)page.getTotal();
        return CommonResult.success(goodsStockLogList,total);
    }

}
